﻿#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<memory>
#include"list.h"
// 内置类型和⾃定义类型之间

// 1、⾃定义类型=内置类型->构造函数⽀持
// 2、内置类型=⾃定义类型->operator内置类型⽀持

class A
{
public:
	// 构造函数加上explicit就不⽀持隐式类型转换了

		//explicit A(int a)
	A(int a)
		:_a1(a)
		, _a2(a)
	{
	}
	A(int a1, int a2)
		:_a1(a1)
		, _a2(a2)
	{
	}
	// 加上	explicit不⽀持隐式类型转换了

	// explicit operator int()
	//不支持这种写法int operator () const
	operator int() const
	{
		return _a1 + _a2;
	}
private:
	int _a1 = 1;
	int _a2 = 1;
};
class B
{
public:
	B(int b)
		:_b1(b)
	{
	}
	// ⽀持	A类型对象转换为B类型对象

	B(const A& aa)
		:_b1(aa)
	{
	}
private:
	int _b1 = 1;
};
void func(A a)
{

}
void test()
{
	//// 单参数的转换
	//A aa1 = 1;
	//A aa2 = (A)1;
	//func(1);//隐式类型转换
	//string s1("1111111");//直接构造
	//string s2 = "1111111";//拷贝构造再优化
	//// 多参数的转换

	//A aa3 = { 2,2 };
	//const A& aa4 = { 2,2 };
	//int z = aa1.operator int();
	//int x = aa1;
	//int y = (int)aa2;
	//cout << x << endl;
	//cout << y << endl;
	//cout << z << endl;
	std::shared_ptr<int> foo;
	std::shared_ptr<int> bar(new int(34));
	//if (foo.operator bool())
	if (foo)
		std::cout << "foo points to " << *foo << '\n';
	else
		std::cout << "foo is null\n";
	if (bar)
		std::cout << "bar points to " << *bar << '\n';
	else
		std::cout << "bar is null\n";
	// A类型对象隐式转换为B类型

	/*B bb1 = aa1;
	B bb2(2);
	bb2 = aa1;
	const B& ref1 = aa1;*/
}
void test2()
{
	Boogiepop::list<int> lt = { 1,2,3,4,5 };

	//权限缩⼩？权限缩⼩和放⼤，仅限于const的指针和引⽤
	//这⾥不是权限缩⼩，这⾥是⾃定义类型=⾃定义类型之间的类型转换
	//具体实现看下⾯ListIterator中对应的构造函数的实现

	Boogiepop::list<int>::const_iterator cit = lt.begin();
	while (cit != lt.end())
	{
		cout << *cit << " ";
		++cit;
	}
	cout << endl;
}
void insert(size_t pos, char ch)
{
	//这⾥当pos == 0时，就会引发由于隐式类型转换
	// end跟pos⽐较时，提升为size_t导致判断结束逻辑出现问题

	// 在数组中访问挪动数据就会出现越界，经典的类型安全问题

	int end = 10;
	while (end >= pos)
	{
		// ...
		cout << end << endl; --end;
	}
}
void test3()
{
	insert(5, 'x');
	//insert(0, 'x');
	// 	这⾥会本质已经出现了越界访问，只是越界不⼀定能被检查出来

	int x = 100;
	double* p1 = (double*)&x;
	cout << *p1 << endl;
	const int y = 0;//可以利用关键字volatile来避免优化
	int* p2 = (int*)&y;
	(*p2) = 1;
	// 	这⾥打印的结果是1和	0，也是因为我们类型转换去掉了const属性

	// 	但是编译器认为	y是const的，不会被改变，所以会优化编译时放到

	// 寄存器或者直接替换y为0导致的
	volatile const int z = 0;
	int* p3 = (int*)&z;
	(*p3) = 1;
	// 	这⾥打印的结果是1和	0，也是因为我们类型转换去掉了const属性
	cout << *p2 << endl;
	cout << y << endl;
	cout << *p3 << endl;
	cout << z << endl;
}
int main()
{
	//test2();
	test3();
	return 0;
}
